/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.ndx.majick.properties.impl;

import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.beans.VetoableChangeSupport;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.ndx.majick.properties.VetoableProperty;

/**
 *
 * @author Maison
 */
public class DefaultVetoableProperty<Type extends Object> extends DefaultProperty<Type> implements VetoableProperty<Type> {
    /**
     * Veto change support, used to send veto events
     */
    private transient final VetoableChangeSupport vetoSupport;
    
    /**
     * Build a vetoable property, with all required infos
     * @param type
     * @param name
     * @param support
     * @param vetoSupport
     */
    public DefaultVetoableProperty(Class<? extends Type> type, String name, PropertyChangeSupport support, VetoableChangeSupport vetoSupport) {
        super(type, name, support);
        this.vetoSupport = vetoSupport;
    }

    public DefaultVetoableProperty(Class<? extends Type> type, String name, PropertyChangeSupport support, VetoableChangeSupport vetoSupport, Type value) {
        this(type, name, support, vetoSupport);
        set(value);
    }
    
    /**
     * As stated by reference interface, this implementation delegates its work to {@link #setVeto(java.lang.Object)}
     * @param newValue
     * @deprecated see {@link VetoableProperty#set(java.lang.Object)} for more info
     */
    @Override
    public void set(Type newValue) {
        try {
            setVeto(newValue);
        } catch (PropertyVetoException ex) {
            Logger.getLogger(DefaultVetoableProperty.class.getName()).log(Level.FINEST, null, ex);
        }
    }

    public void setVeto(Type newValue) throws PropertyVetoException {
        if(!equalsValue(newValue)) {
            Type oldValue = value;
            value = newValue;
            try {
                vetoSupport.fireVetoableChange(getName(), oldValue, newValue);
                support.firePropertyChange(getName(), oldValue, newValue);
            } catch(PropertyVetoException e) {
                /* If property modification failed, we rollback value, but do not send any event, since it's not needed in that case */
                value = oldValue;
                throw e;
            }
        }
    }

    public void addVetoableChangeListener(VetoableChangeListener listener) {
        vetoSupport.addVetoableChangeListener(getName(), listener);
    }

    public void removeVetoableChangeListener(VetoableChangeListener listener) {
        vetoSupport.removeVetoableChangeListener(getName(), listener);
    }

}
